package com.mini.util;

import org.apache.commons.lang3.time.DateUtils;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Created by li on 2017/10/27.
 */
public class DateUtil extends DateUtils {


    public static final String SHORT_DATA_FORMAT_YYYY_MMDD = "yyyy/MMdd";


    public static String getFormatString(Date date,String format) {
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        return sdf.format(date);
    }

    public static String getTodayString() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

        return sdf.format(new Date());
    }

    public static String getTomorrowString() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.DATE,   +1);

        return sdf.format(cal.getTime());
    }

    public static String getYesterdayString() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.DATE,   -1);

        return sdf.format(cal.getTime());
    }

    public static String getMyDayString(int n) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.DATE,   n);

        return sdf.format(cal.getTime());
    }

    public static String getMyDayString(Date date,int n) {
        Calendar calbase = Calendar.getInstance();
        calbase.setTime(date);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

        calbase.add(Calendar.DATE,   n);

        return sdf.format(calbase.getTime());
    }

    public static Date getMyDay(Date date,int n) {
        Calendar calbase = Calendar.getInstance();
        calbase.setTime(date);
        calbase.add(Calendar.DATE,   n);

        return calbase.getTime();
    }

    public static Date getMyDayBegin(Date date,int n) {
        Calendar calbase = Calendar.getInstance();
        calbase.setTime(date);
        calbase.add(Calendar.DATE,   n);
        calbase.set(Calendar.HOUR_OF_DAY,   0);
        calbase.set(Calendar.MINUTE, 0);
        calbase.set(Calendar.SECOND, 0);
        calbase.set(Calendar.MILLISECOND, 0);

        return calbase.getTime();
    }

    public static Date getMyDayHour(Date date,int n) {
        Calendar calbase = Calendar.getInstance();
        calbase.setTime(date);
        calbase.add(Calendar.HOUR_OF_DAY,   n);
        calbase.set(Calendar.MINUTE, 0);
        calbase.set(Calendar.SECOND, 0);
        calbase.set(Calendar.MILLISECOND, 0);
        return calbase.getTime();
    }

    public static Date getMyDayHourF(Date date,Integer mins) {
        Calendar calbase = Calendar.getInstance();
        calbase.setTime(date);
        if(mins != null){
            calbase.add(Calendar.MINUTE, mins);
        }else{
            calbase.set(Calendar.MINUTE, 0);
        }

        calbase.set(Calendar.SECOND, 0);
        calbase.set(Calendar.MILLISECOND, 0);
        return calbase.getTime();
    }
    public static Date getMyDaySecF(Date date,Integer seconds) {
        Calendar calbase = Calendar.getInstance();
        calbase.setTime(date);
        if(seconds != null){
            calbase.add(Calendar.SECOND, seconds);
        }else{
            calbase.set(Calendar.SECOND, 0);
        }

        calbase.set(Calendar.MINUTE, 0);
        calbase.set(Calendar.MILLISECOND, 0);
        return calbase.getTime();
    }

    public static Date getMyDayHour(Date date) {
        Calendar calbase = Calendar.getInstance();
        calbase.setTime(date);
        calbase.set(Calendar.MINUTE, 59);
        calbase.set(Calendar.SECOND, 59);
        calbase.set(Calendar.MILLISECOND, 0);
        return calbase.getTime();
    }

    public static String getDateString(Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

        return sdf.format(date);
    }

    public static Date getStringToDate(String strDate) {

        Date date = null;
        try {
            DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

            date = sdf.parse(strDate);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date;
    }

    public static String getDatetimeString(Date date) {
        SimpleDateFormat sdfAll = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        return sdfAll.format(date);
    }

    public static String getBeginMinutesDatetimeString(Date date) {

        SimpleDateFormat sdfAll = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        Calendar cal = Calendar.getInstance();

        cal.setTime(date);
        cal.set(Calendar.SECOND, 0);

        return sdfAll.format(cal.getTime());
    }

    public static String getEndMinutesDatetimeString(Date date) {

        SimpleDateFormat sdfAll = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.SECOND, 59);

        return sdfAll.format(cal.getTime());
    }

    public static String getDateStringInAllFormat(Date date) {
        SimpleDateFormat sdfAll = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return sdfAll.format(date);
    }

    /**
     * 获取本周的起始日期，结束日期。list的size为2，起始和结束日期
     * @return
     */
    public static List<String> getBeginAndEndDateStringOfCurrentWeek() {

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

        Calendar c = Calendar.getInstance();
        int day_of_week = c.get(Calendar.DAY_OF_WEEK) - 1;
        if (day_of_week == 0){
            day_of_week = 7;
        }
        c.add(Calendar.DATE, -day_of_week + 1);
        String beginStr = sdf.format(c.getTime());

        Calendar c2 = Calendar.getInstance();
        int day_of_week2 = c2.get(Calendar.DAY_OF_WEEK) - 1;
        if (day_of_week2 == 0){
            day_of_week2 = 7;
        }
        c2.add(Calendar.DATE, -day_of_week2 + 7);
        String endStr = sdf.format(c2.getTime());
        return Arrays.asList(beginStr, endStr);
    }

    /**
     * 获取本月的起始日期，结束日期。list的size为2，起始和结束日期
     * @return
     */
    public static List<String> getBeginAndEndDateStringOfCurrentMonth() {

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

        Calendar c = Calendar.getInstance();
        c.add(Calendar.MONTH, 0);
        c.set(Calendar.DAY_OF_MONTH,1);//设置为1号,当前日期既为本月第一天
        String beginStr = sdf.format(c.getTime());

        c.set(Calendar.DAY_OF_MONTH, c.getActualMaximum(Calendar.DAY_OF_MONTH));
        String endStr = sdf.format(c.getTime());

        return Arrays.asList(beginStr, endStr);
    }

    public static Date parseToDefaultFormat(String dateString) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        return sdf.parse(dateString);
    }

    public static Date parseToDateTimeFormat(String dateTimeString) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        return sdf.parse(dateTimeString);
    }

    public static String getSimpleDateFormat(Date nowDate) throws ParseException {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");

        return dateFormat.format(nowDate);
    }

    public static String getYyyyMMddDateFormat(Date nowDate) throws ParseException {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");

        return dateFormat.format(nowDate);
    }
    public static boolean isRightRange(String beginString, String endString) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date beginDate = sdf.parse(beginString);
        Date endDate = sdf.parse(endString);

        return endDate.getTime() >= beginDate.getTime();
    }

    public static List<Date> getBetweenDates(Date begin, Date end) {
        List<Date> result = new ArrayList<Date>();
        Calendar tempStart = Calendar.getInstance();
        tempStart.setTime(begin);

        while(begin.getTime()<=end.getTime()){
            result.add(tempStart.getTime());
            tempStart.add(Calendar.DAY_OF_YEAR, 1);
            begin = tempStart.getTime();
        }
        return result;
    }

    /**
     * 从begin（包含）这天开始，连续取num天的日期；num<0时，是往前取日期列表
     * @param begin
     * @param num
     * @return
     */
    public static List<Date> getBetweenDates(Date begin, Integer num) {
        List<Date> result = new ArrayList<Date>();
        Calendar tempStart = Calendar.getInstance();
        tempStart.setTime(begin);

        for(int i=0; i < Math.abs(num); i++){
            result.add(tempStart.getTime());
            tempStart.add(Calendar.DAY_OF_MONTH, (Math.abs(num)/num));
        }
        return result;
    }

    /**
     * 固定字符串日期格式为'yyyy-MM-dd'
     * @param begin
     * @param end
     * @return
     */
    public static List<String> getBetweenDates(String begin, String end) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date beginDate = sdf.parse(begin);
        Date endDate = sdf.parse(end);

        List<Date> dateList = getBetweenDates(beginDate, endDate);
        List<String> dateStrList = dateList.stream().map(date -> sdf.format(date)).collect(Collectors.toList());

        return dateStrList;
    }

    public static boolean fallInDateSection(Date target, Date start, Date end) {
        return target.after(start) && target.before(end);
    }

    /**
     * 获取一天的起始时间, 如果2018-05-05 00:00:00
     * @param date
     * @return
     */
    public static Date getTheBegin(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);

        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);

        return calendar.getTime();
    }

    public static Date getTheBeginHour(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);

//        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);

        return calendar.getTime();
    }

    /**
     * 获取一天的终止时间, 如果2018-05-05 23:59:59
     * @param date
     * @return
     */
    public static Date getTheEnd(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);

        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
//        calendar.set(Calendar.MILLISECOND, 0);

        return calendar.getTime();
    }

    /**
     * 获取某天的整点时刻
     * @param date
     * @param hour
     * @return
     */
    public static Date getAndSetTimeOfOneDay(Date date, Integer hour) {
        return getAndSetTimeOfOneDay(date, hour, 0);
    }
    public static Date getAndSetTimeOfOneDay(Date date, Integer hour, Integer minute) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);

        calendar.set(Calendar.HOUR_OF_DAY, hour);
        calendar.set(Calendar.MINUTE, minute);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);

        return calendar.getTime();
    }

    public static Integer getRemainSecondsOneDay(Date currentDate) {
        LocalDateTime midnight = LocalDateTime.ofInstant(currentDate.toInstant(),
                ZoneId.systemDefault()).plusDays(1).withHour(0).withMinute(0)
                .withSecond(0).withNano(0);
        LocalDateTime currentDateTime = LocalDateTime.ofInstant(currentDate.toInstant(),
                ZoneId.systemDefault());
        long seconds = ChronoUnit.SECONDS.between(currentDateTime, midnight);
        return (int) seconds;
    }

    public static Date getDateByMillisecond(Long dateTimeMill) {
        Date dateTime = new Date(dateTimeMill);
        return dateTime;
    }

    public static String getHourMinsSeconds(Long dateTimeMill) {
        long hour = dateTimeMill/(60*60*1000);
        long mins = (dateTimeMill- hour*60*60*1000)/(60*1000);
        long seconds =(dateTimeMill- hour*60*60*1000 - mins*60*1000)/1000;
        return hour +":"+mins+":"+seconds;
    }

    /**
     * 按照当天日期获取随机数，判断20%以下显示
     *
     * @return
     */
    public static Boolean isRandomUserGoal(){

        Boolean flag = false;
        try {
            String currencyDate = DateUtil.getYyyyMMddDateFormat(new Date());

            Random random = new Random(Integer.parseInt(currencyDate));

            int nextInt = random.nextInt(10);

            if (nextInt < 2) { //小于20%进行显示
                flag = true;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return flag;
    }

    /**
     * 判断开始时间是否大于当前时间
     *
     * @param appointDate
     * @return
     * @throws ParseException
     */
    public static Boolean isBeforeAndAfter(Date appointDate) {

        boolean flag = false;

        try {
            Date currency = getStringToDate(getTodayString());

            Date d = getStringToDate(getDateString(appointDate));

            if (d.getTime() >= currency.getTime()) {
                flag = true;
            }
        } catch ( Exception e ) {
            e.printStackTrace();
        }
        return flag;
    }



    public static void main(String[] args) throws ParseException {

        System.out.println(DateUtil.isBeforeAndAfter(new Date()));

//        List<String> l1 = getBeginAndEndDateStringOfCurrentMonth();
//        List<String> l2 = getBeginAndEndDateStringOfCurrentWeek();
//        String yesterday = getYesterdayString();
//
//        String str1 = getBeginMinutesDatetimeString(new Date());
//        String str2 = getEndMinutesDatetimeString(new Date());
//
//        System.out.println(str1);
//        System.out.println(str2);

//        Date hourlyDate = DateUtil.getAndSetTimeOfOneDay(new Date(), 12, 1);
//        System.out.println(hourlyDate);
//
//        Date date = DateUtil.parseToDateTimeFormat("2018-06-06 17:40:36");
//
//        System.out.println(date.before(hourlyDate));
//        List<String> stringList = DateUtil.getBetweenDates("2019-05-26" , "2019-05-25");
//        System.out.println(stringList.size());

    }
}
